-- String
-- Create by weism
-- 字符串函数的一些接口扩充

-- 将字符串打断
function string.explode2(str, sep)
    local t = str;
    local m = {};

    while true do
        local index = string.find(t, sep);
        if (not index) then
            table.insert(m, t);
            return m;
        end

        table.insert(m, string.sub(t, 1, index - 1));
        t = string.sub(t, index + 1);
    end

    -- 不会执行到这里的
    assert(false);
end

-- 将字符串打断(效率更高些)
function string.explode(str, sep)
    if sep == nil then
        sep = "%s"
    end
    local t = {};
    local i = 1;
    for str in string.gmatch(str, "([^"..sep.."]+)") do
        t[i] = str;
        i = i + 1;
    end
    return t;
end

-- 拼接起来
function string.implode(arr, sep)
    if #arr <= 0 then
        return;
    end

    local ret = arr[1];
    for index = 2, #arr do
        ret = ret .. sep .. arr[index];
    end

    return ret;
end

-- 过滤前后的空格等
function string.trim(str)
    --local _, __, r = string.find(str, "[ \r]*(.*)[ \r]*");
    --return r;
    return (string.gsub(str, "^%s*(.-)%s*$", "%1"));
end

-- 判断字符串s是不是以w开头
function string.startWith(s, w)
    return string.sub(s, 1, string.len(w)) == w;
end

-- 判断字符串s是不是以w结尾
function string.endWith(s, w)
    return string.sub(s, -string.len(w), -1) == w;
end

-- 获取当前符号宽度
local function getWCharByteCount(curByte)
    local byteCount = 1;
    if curByte>0 and curByte<=127 then
        byteCount = 1;
    elseif curByte>=192 and curByte<223 then
        byteCount = 2;
    elseif curByte>=224 and curByte<=239 then
        byteCount = 3;
    elseif curByte>=240 and curByte<=247 then
        byteCount = 4;
    end
    return byteCount;
end

-- 修正评论换行
function string.fixContent(str, fontSize, maxWidth)
    local lenInByte = #str;
    local retArr = {};
    local i = 1;
    local startPos = 1;
    local endPos = 0;
    -- 测试Label
    local testLabel = ccui.Text:create();
    testLabel:setFontSize(fontSize);

    repeat
        local curByte = string.byte(str, i);
        local byteCount = getWCharByteCount(curByte);

        if i == startPos and curByte == 32 then
            -- 开头是空格，修正startPos
            startPos = startPos + byteCount;
        end

        i = i + byteCount;
        endPos = i - 1;

        testLabel:setString(string.sub(str, startPos, endPos));
        -- 超过指定宽度
        if testLabel:getVirtualRenderer():getContentSize().width >= maxWidth then
            table.insert(retArr, string.sub(str, startPos, endPos));
            startPos = endPos + 1;
        end
    until i > lenInByte;

    if startPos <= endPos then
        table.insert(retArr, string.sub(str, startPos, endPos));
    end

    return retArr;
end

-- 获取字符串宽度
function string.getWCharWidth(str, fontSize)
    local lenInByte = #str;
    if lenInByte == 0 then
        return 0;
    end

    local width = 0;

    local i = 1;
    repeat
        local curByte = string.byte(str, i);
        local byteCount = getWCharByteCount(curByte);

        i = i + byteCount;

        if byteCount == 1 then
            width = width + fontSize * 0.5;
        else
            width = width + fontSize;
        end
    until i > lenInByte;

    return width;
end

-- 获取字符串的字节数（127以内算1，其余算2）
function string.getByteCount(str)
    if not str then -- TODO
        return 0;
    end

    local lenInByte = #str;
    if lenInByte == 0 then
        return 0;
    end

    local count = 0;

    local i = 1;
    repeat
        local curByte = string.byte(str, i);
        local byteCount = math.min(getWCharByteCount(curByte), 2);

        i = i + byteCount;

        count = count + 1;
    until i > lenInByte;

    return count;
end

-- 获取字符个数，宽字符算一个
function string.getWCharCount(str)
    if not str then -- TODO
        return 0;
    end

    local lenInByte = #str;
    if lenInByte == 0 then
        return 0;
    end

    local count = 0;

    local i = 1;
    repeat
        local curByte = string.byte(str, i);
        local byteCount = getWCharByteCount(curByte);

        i = i + byteCount;

        count = count + 1;
    until i > lenInByte;

    return count;
end

-- 是否泰语特殊字符(如声调符号等)
function string.isSpecialCharForThai(str)
    local list = {
        -- "\xe0\xb8\xb1",
        -- "\xe0\xb8\xb3",
        -- "\xe0\xb8\xb4",
        -- "\xe0\xb8\xb5",
        -- "\xe0\xb8\xb6",
        -- "\xe0\xb8\xb7",
        -- "\xe0\xb8\xb8",
        -- "\xe0\xb8\xb9",
        -- "\xe0\xb8\xba",
        -- "\xe0\xb9\x87",
        -- "\xe0\xb9\x88",
        -- "\xe0\xb9\x89",
        -- "\xe0\xb9\x8a",
        -- "\xe0\xb9\x8b",
        -- "\xe0\xb9\x8c",
        -- "\xe0\xb9\x8d",
        -- "\xe0\xb9\x8e",
        "ุ","ู","ึ","ี","ั","ื","ิ","๊","็","๋","์","่","้","ํ","ฺ",
    };

    if table.indexOf(list, str) ~= -1 then
        return true;
    end

    return false;
end

-- 获取泰语字符个数，宽字符算一个
-- 泰语字符有不占位置的，统计个数时需要剔除掉
function string.getWCharCountForThai(str)
    if not str then -- TODO
        return 0;
    end

    local lenInByte = #str;
    if lenInByte == 0 then
        return 0;
    end

    local count = 0;

    local charNum = string.getWCharCount(str);

    for i = 1, charNum do
        local c = string.getWChar(str, i); -- 此处的c，可能为3个字节
        if not string.isSpecialCharForThai(c) then
            count = count + 1;
        end
    end

    return count;
end

--------------------
-- 是否换行符
function string.isBreakLineChar(str, pos)
    local lenInByte = #str;
    if lenInByte == 0 then
        return false;
    end

    local count = 0;

    local i = 1;
    repeat
        local curByte = string.byte(str, i);
        local byteCount = getWCharByteCount(curByte);

        i = i + byteCount;

        if pos == count and curByte == 10 then
            return true;
        end

        count = count + 1;

    until i > lenInByte;

    return false;
end

--------------------
-- 获取字符
function string.getWChar(str, pos)
    local lenInByte = #str;
    if lenInByte == 0 then
        return "";
    end

    local count = 1;

    local i = 1;
    repeat
        local curByte = string.byte(str, i);
        local byteCount = getWCharByteCount(curByte);

        local from = i;
        i = i + byteCount;

        if pos == count then
            return string.sub(str, from, i - 1);
        end

        count = count + 1;

    until i > lenInByte;

    return "";
end

-- 解析json串
function string.parseJsonToTable(str)
    local data = catch(function() return json.decode(str, 1) end);

    if type(data) == "table" then
        return data;
    end

    return {};
end

